//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace Eas.WebCrawler.Common.Diagnostics {
    /// <summary>Used for wrapping a value type with a reference type for high-performance trace scenarios.</summary>
    /// <typeparam name="_T">The type to be wrapped</typeparam>
    public class ReferenceTypeWrapper<_T> :IFormattable, IEquatable<_T>, IEquatable<ReferenceTypeWrapper<_T>> where _T : struct, IFormattable, IEquatable<_T> {
        /// <summary>The underlying value of this instance</summary>
        /// <remarks>Backing field for the Value property.</remarks>
        /// <seealso cref="Value"/>
        private _T _Value;

        /// <summary>Creates an instance of this class from a specified value.</summary>
        /// <param name="wrappedValue">The value to wrap.</param>
        public ReferenceTypeWrapper(_T wrappedValue) {
            _Value = wrappedValue;
        }

        /// <summary>The underlying value of this instance</summary>
        public _T Value {
            get { return _Value; }
            set { _Value = value; }
        }

        /// <summary>Converts the underlying value to a string.</summary>
        /// <returns>The underlying value converted to a string.</returns>
        public override string ToString() {
            return _Value.ToString();
        }

        /// <summary>Converts the underlying value to a string.</summary>
        /// <param name="format">The format parameters to use when formatting.</param>
        /// <returns>The underlying value converted to a string.</returns>
        public string ToString(string format) {
            return _Value.ToString(format, System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
        }

        /// <summary>Converts the underlying value to a string.</summary>
        /// <param name="format">The format parameters to use when formatting.</param>
        /// <param name="formatProvider">The format provider to use for formatting.</param>
        /// <returns>The underlying value converted to a string.</returns>
        public string ToString(string format, IFormatProvider formatProvider) {
            return _Value.ToString(format, formatProvider);
        }

        /// <summary>Checks for equality between this instance and the specified object.</summary>
        /// <param name="obj">The object to compare.</param>
        /// <returns><code>true</code> if the objects are equal, otherwise false.</returns>
        public override bool Equals(object obj) {
            ReferenceTypeWrapper<_T> other = obj as ReferenceTypeWrapper<_T>;
            if (other != null) return this.Equals(other);

            if (! (obj is _T) ) return false;
            return this.Equals( (_T)obj);
        }

        /// <summary>Returns the hashcode of this instance's underlying <see cref="Value"/>.</summary>
        /// <returns>The hashcode of this instance's <see cref="Value"/>.</returns>
        public override int GetHashCode() {
            return _Value.GetHashCode();
        }

        #region IEquatable<ReferenceTypeWrapper<_T>> Members

        /// <summary>Checks if the passed in wrapper's underlying <see cref="Value"/> is the same as this instance's <see cref="Value"/>.</summary>
        /// <param name="other">The instance to compare.</param>
        /// <returns><code>true</code> if the values are equal, otherwise false.</returns>
        public bool Equals(ReferenceTypeWrapper<_T> other) {
            return _Value.Equals(_Value);
        }

        #endregion

        #region IEquatable<_T> Members

        /// <summary>Checks if the passed in value is that same as this instance's <see cref="Value"/>.</summary>
        /// <param name="other">The instance to compare.</param>
        /// <returns><code>true</code> if the values are equal, otherwise false.</returns>
        public bool Equals(_T other) {
            return _Value.Equals(other);
        }

        #endregion
    }
}
